package com.example.resubmit.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.DigestUtils;

import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 关于重复提交锁
 *
 * @author james
 */
@Slf4j
public class ResubmitLock {
    /**
     * 私有构造方法  只允许单例 来创建
     */
    private ResubmitLock() {
    }

    private static class SinletonInstance {
        private static final ResubmitLock INSTANCE = new ResubmitLock();
    }
    public static ResubmitLock getInstance() {
        return SinletonInstance.INSTANCE;
    }

    /**
     * LOCK_CACHE 保存已经提交过的请求的key(可以用提交的内容做md5运算, hash运算后的值做key)
     */
    private static final ConcurrentHashMap<String, Object> LOCK_CACHE = new ConcurrentHashMap<>(16);
    /**
     * 定时器, 用于删除key
     */
    private static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(5, new ThreadPoolExecutor.DiscardPolicy());

    /**
     * md5 加密
     * @param param
     * @return
     */
    public static String handleKey(String param) {
        String key = param == null ? "" : param;
        return DigestUtils.md5DigestAsHex(key.getBytes());
    }

    public boolean lock(final String key, Object value){
        return Objects.isNull(LOCK_CACHE.putIfAbsent(key,value));
    }

    public void unLock(final boolean lock,final String key,final int delaySeconds){
        if (lock){
            EXECUTOR.schedule(()->LOCK_CACHE.remove(key),delaySeconds, TimeUnit.SECONDS);
        }
    }

}
